package com.kakarote.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.kakarote.common.log.entity.OperationLog;
import com.kakarote.common.log.enums.BehaviorEnum;
import com.kakarote.core.common.Const;
import com.kakarote.core.entity.BasePage;
import com.kakarote.core.entity.QueryParentDeptBO;
import com.kakarote.core.entity.UserInfo;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.entity.SimpleUser;
import com.kakarote.core.feign.admin.service.AdminService;
import com.kakarote.core.servlet.ApplicationContextHolder;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.core.utils.BaseUtil;
import com.kakarote.core.utils.SeparatorUtil;
import com.kakarote.core.utils.UserCacheUtil;
import com.kakarote.core.utils.UserUtil;
import com.kakarote.oa.common.OaCodeEnum;
import com.kakarote.oa.entity.BO.OaLogTemplateConfigQueryBO;
import com.kakarote.oa.entity.BO.OaLogTemplateConfigSaveBO;
import com.kakarote.oa.entity.PO.OaLogRule;
import com.kakarote.oa.entity.PO.OaLogTemplateConfig;
import com.kakarote.oa.entity.VO.OaLogTemplateConfigListVO;
import com.kakarote.oa.entity.VO.OaLogTemplateConfigVO;
import com.kakarote.oa.mapper.OaLogTemplateConfigMapper;
import com.kakarote.oa.service.IOaLogRuleService;
import com.kakarote.oa.service.IOaLogTemplateConfigService;
import com.kakarote.oa.service.IOaLogTemplateFieldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wanli
 * 针对表【wk_oa_log_template(日志模板设置表)】的数据库操作Service实现
 * @date 2022-07-04 14:54:18
 */
@Service
public class OaLogTemplateConfigServiceImpl extends BaseServiceImpl<OaLogTemplateConfigMapper, OaLogTemplateConfig> implements IOaLogTemplateConfigService {

    @Autowired
    private IOaLogTemplateFieldService oaLogTemplateFieldService;
    @Autowired
    private AdminService adminService;
    @Autowired
    private IOaLogRuleService oaLogRuleService;

    /**
     * 一级一级向上找到level参数的位置的userId
     *
     * @param userInfos 所有用户list
     * @param userId    userId
     * @param level     等级（限制递归次数）
     * @return 按照等级从低到高排列的userId
     */
    private List<Long> queryParentsSortByLevel(List<UserInfo> userInfos, Long userId, Integer level) {
        List<Long> userIds = new ArrayList<>();
        if (ObjectUtil.equal(0, level)) {
            return userIds;
        }
        if (ObjectUtil.isNotNull(userId) && userId > 0) {
            for (UserInfo user : userInfos) {
                if (ObjectUtil.equal(userId, user.getUserId())) {
                    userIds.add(userId);
                    userIds.addAll(queryParentsSortByLevel(userInfos, user.getParentId(), level - 1));
                }
            }
        }
        return userIds;
    }

    @Override
    public List<Long> searchParentUserIds(List<Integer> parentLevels) {
        List<Long> ids = new ArrayList<>();
        if (ObjectUtil.isNotNull(parentLevels) && !parentLevels.isEmpty()) {
            UserInfo userInfo = UserCacheUtil.getUserInfo(UserUtil.getUserId());
            if (ObjectUtil.isNotNull(userInfo.getParentId()) && userInfo.getParentId() > 0) {
                List<UserInfo> userInfos = ApplicationContextHolder.getBean(AdminService.class).queryUserInfoList().getData();
                // 将上级list升序
                List<Integer> parentLevelsAsc = parentLevels.stream().sorted().collect(Collectors.toList());
                // 此处传入当前用户的上级、配置中的最高级，返回值按照等级升序排列
                List<Long> parentUserIds = this.queryParentsSortByLevel(userInfos, userInfo.getParentId(), CollUtil.getLast(parentLevelsAsc));
                int parentMount = parentUserIds.size();
                if (parentMount > 0) {
                    for (Integer level : parentLevels) {
                        if (level <= parentMount) {
                            // 等级作为下标，取各等级的userId
                            ids.add(CollUtil.get(parentUserIds, level - 1));
                        }
                    }
                }
            }
        }
        return ids;
    }

    @Override
    public BasePage<OaLogTemplateConfigListVO> queryList(OaLogTemplateConfigQueryBO page) {
        Long deptId = UserUtil.getUser().getDeptId();
        List<Long> deptIds = new ArrayList<>();
        deptIds.add(deptId);
        if (!UserUtil.isAdmin()) {
            QueryParentDeptBO queryBO = new QueryParentDeptBO();
            queryBO.setDeptId(deptId);
            queryBO.setLevel(20);
            List<Long> ids = adminService.queryParentDeptIdByLevel(queryBO).getData();
            CollUtil.addAll(deptIds, ids);
        }
        BasePage<OaLogTemplateConfig> basePage = this.getBaseMapper().queryList(
                page.parse()
                , UserUtil.isAdmin()
                , page.getIsPart()
                , UserUtil.getUserId()
                , deptId
                , deptIds
        );
        BasePage<OaLogTemplateConfigListVO> voPage = new BasePage<>(basePage.getCurrent(), basePage.getSize(), basePage.getTotal());
        List<OaLogTemplateConfigListVO> voList = new ArrayList<>();
        for (OaLogTemplateConfig temp : basePage.getList()) {
            OaLogTemplateConfigListVO vo = new OaLogTemplateConfigListVO();
            BeanUtil.copyProperties(temp, vo);
            vo.setCreateUserName(ObjectUtil.equal(0L, temp.getCreateUserId()) ? "系统默认" : UserCacheUtil.getUserName(temp.getCreateUserId()));
            vo.setUpdateUserName(ObjectUtil.isNotNull(temp.getUpdateUserId()) ? UserCacheUtil.getUserName(temp.getUpdateUserId()) : "");
            // 可见范围
            if (StrUtil.isNotEmpty(temp.getUserIds())) {
                Set<Long> userIds = SeparatorUtil.toLongSet(temp.getUserIds());
                if (CollUtil.isNotEmpty(userIds)) {
                    List<SimpleUser> listResult = UserCacheUtil.getSimpleUsers(userIds);
                    vo.setUserList(listResult);
                }
            }
            if (StrUtil.isNotEmpty(temp.getDeptIds())) {
                Set<Long> deptIdsSet = SeparatorUtil.toLongSet(temp.getDeptIds());
                if (CollUtil.isNotEmpty(deptIdsSet)) {
                    vo.setDeptList(UserCacheUtil.getDeptList(deptIdsSet));
                }
            }
            Map<String, String> keyMap = new HashMap<>();
            keyMap.put("name_resourceKey", "oa.log.template.config." + temp.getName());
            vo.setLanguageKeyMap(keyMap);
            voList.add(vo);
        }
        voPage.setList(voList);
        return voPage;
    }

    @Override
    public OaLogTemplateConfigVO detail(Long configId, Boolean needFieldsFlag) {
        OaLogTemplateConfig temp = this.lambdaQuery().eq(OaLogTemplateConfig::getId, configId).one();
        if (ObjectUtil.isNotNull(temp)) {
            OaLogTemplateConfigVO vo = BeanUtil.copyProperties(temp, OaLogTemplateConfigVO.class);
            if (needFieldsFlag) {
                vo.setFormList(oaLogTemplateFieldService.queryFormPositionField(temp.getId(), true));
            }
            if (ObjectUtil.equal(temp.getRuleStatus(), 1)) {
                OaLogRule rule = oaLogRuleService.getByConfigId(vo.getId());
                vo.setLogRule(rule);
            }

            // 适用  范围-部门
            if (ObjectUtil.isNotNull(temp.getDeptIds())) {
                List<Long> deptList = new ArrayList<>(SeparatorUtil.toLongSet(temp.getDeptIds()));
                vo.setDeptIds(deptList);
                vo.setDeptList(UserCacheUtil.getDeptList(deptList));
            }
            // 适用  范围-用户
            if (ObjectUtil.isNotNull(temp.getUserIds())) {
                List<Long> userIds = new ArrayList<>(SeparatorUtil.toLongSet(temp.getUserIds()));
                vo.setUserIds(userIds);
                List<SimpleUser> listResult = UserCacheUtil.getSimpleUsers(userIds);
                vo.setUserList(listResult);
            }
            // 发送  范围-上级
            if (ObjectUtil.isNotNull(temp.getParentLevels())) {
                List<Integer> parentLevels = JSON.parseArray(temp.getParentLevels(), Integer.class);
                vo.setParentLevelList(parentLevels);
                List<Long> parentUserIds = this.searchParentUserIds(parentLevels);
                List<SimpleUser> simpleUsers = UserCacheUtil.getSimpleUsers(parentUserIds);
                vo.setParentLevelUserList(simpleUsers);
            }
            // 发送  范围-部门
            if (ObjectUtil.isNotNull(temp.getSendDeptIds())) {
                List<Long> list = JSON.parseArray(temp.getSendDeptIds(), Long.class);
                vo.setSendDeptIdList(list);
                vo.setSendDeptList(UserCacheUtil.getDeptList(list));
            }
            // 发送  范围-用户
            if (ObjectUtil.isNotNull(temp.getSendUserIds())) {
                List<Long> list = JSON.parseArray(temp.getSendUserIds(), Long.class);
                vo.setSendUserIdList(list);
                List<SimpleUser> listResult = UserCacheUtil.getSimpleUsers(list);
                vo.setSendUserList(listResult);
            }
            //多语言
            if (ObjectUtil.isNotNull(temp.getName())) {
                Map<String, String> keyMap = new HashMap<>();
                keyMap.put("name_resourceKey", "oa.log.template.config." + temp.getName());
                vo.setLanguageKeyMap(keyMap);
            }
            return vo;
        }
        return null;
    }

    @Override
    public OperationLog addOrUpdate(OaLogTemplateConfigSaveBO saveBO) {
        if (saveBO.getFormList().isEmpty()) {
            throw new CrmException(OaCodeEnum.LOG_TEMPLATE_FIELDS_EMPTY_ERROR);
        }
        OaLogTemplateConfig config = BeanUtil.copyProperties(saveBO, OaLogTemplateConfig.class);
        Long id = ObjectUtil.isNotNull(saveBO.getId()) ? saveBO.getId() : BaseUtil.getNextId();
        config.setId(id);
        if (ObjectUtil.isNotNull(saveBO.getUserIdList())) {
            Set<Long> list = new HashSet<>(saveBO.getUserIdList());
            config.setUserIds(list.stream().map(String::valueOf).collect(Collectors.joining(Const.SEPARATOR)));
        }
        if (ObjectUtil.isNotNull(saveBO.getDeptIdList())) {
            Set<Long> list = new HashSet<>(saveBO.getDeptIdList());
            config.setDeptIds(list.stream().map(String::valueOf).collect(Collectors.joining(Const.SEPARATOR)));
        }
        config.setParentLevels(JSON.toJSONString(saveBO.getParentLevelList()));
        config.setSendDeptIds(JSON.toJSONString(saveBO.getSendDeptIdList()));
        config.setSendUserIds(JSON.toJSONString(saveBO.getSendUserIdList()));


        OperationLog operationLog = new OperationLog();
        if (ObjectUtil.isNotNull(saveBO.getId())) {
            config.setUpdateTime(LocalDateTime.now());
            config.setUpdateUserId(UserUtil.getUserId());

            operationLog.setOperationObject(config.getName());
            operationLog.setOperationInfo("编辑日志模板：" + config.getName());
            operationLog.setBehavior(BehaviorEnum.UPDATE);

        } else {
            config.setSystemFlag(1);
            if (ObjectUtil.equal(config.getRuleStatus(), 1)) {
                config.setType(saveBO.getLogRule().getType());
            } else {
                config.setType(0);
            }
            config.setStatus(1);
            config.setCreateTime(LocalDateTime.now());
            config.setCreateUserId(UserUtil.getUserId());
            operationLog.setOperationObject(config.getName());
            operationLog.setOperationInfo("新建日志模板：" + config.getName());
            operationLog.setBehavior(BehaviorEnum.SAVE);
        }
        saveOrUpdate(config);
        oaLogTemplateFieldService.saveField(id, saveBO.getFormList());
        oaLogRuleService.saveRule(id, saveBO.getLogRule());


        return operationLog;
    }

    @Override
    public OperationLog updateStatus(Long configId, Integer status) {
        OaLogTemplateConfig log = getById(configId);
        if (ObjectUtil.isNull(log)) {
            throw new CrmException();
        }
        // 系统自带的不能删除、不能停用
        if (ObjectUtil.equal(0, log.getSystemFlag())) {
            if (ObjectUtil.equals(3, status)) {
                throw new CrmException(OaCodeEnum.SYSTEM_LOG_TEMPLATE_CANNOT_DO, "删除");
            } else if (ObjectUtil.equals(2, status)) {
                throw new CrmException(OaCodeEnum.SYSTEM_LOG_TEMPLATE_CANNOT_DO, "停用");
            }
        }


        // 只有停用状态才可以删除
        if (ObjectUtil.equals(3, status)) {
            if (ObjectUtil.notEqual(2, log.getStatus())) {
                throw new CrmException(OaCodeEnum.DELETE_AFTER_STOP);
            }
            log.setStatus(3);
        }

        //停用正在启用的
        if (ObjectUtil.equals(2, status) && ObjectUtil.equal(1, log.getStatus())) {
            log.setStatus(2);
        }

        // 启用正在停用的
        if (ObjectUtil.equals(1, status) && ObjectUtil.equal(2, log.getStatus())) {
            log.setStatus(1);
        }
        updateById(log);

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(log.getName());

        switch (log.getStatus()) {
            case 1:
                operationLog.setBehavior(BehaviorEnum.START);
                break;
            case 2:
                operationLog.setBehavior(BehaviorEnum.STOP);
                break;
            case 3:
                operationLog.setBehavior(BehaviorEnum.DELETE);
                break;
        }
        operationLog.setOperationInfo(operationLog.getBehavior().getName() + "日志模板：" + log.getName());
        return operationLog;
    }


}




